{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## 第一个公钥可搜索加密实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "from charm.toolbox.pairinggroup import PairingGroup, G1, ZR, pair as e\n",
    "from Util import obj2bytes, read_word_as_bytes\n",
    "from hashlib import sha256, md5\n",
    "\n",
    "# 初始化双线性群\n",
    "group = PairingGroup('SS512')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "#### $H_1:\\{0, 1\\}^* \\rightarrow G_1$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def H1(b):\n",
    "    return group.hash(sha256(b).hexdigest(), G1)\n",
    "\n",
    "def H2(b):\n",
    "    return md5(b).hexdigest()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "#### 1. setup:\n",
    "$A$ 选择随机数$\\alpha \\in Z_p^*$以及群$G_1$的生成元$g$,输出私钥sk=$\\alpha$以及公钥pk=$(g, h = g^\\alpha)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def setup():\n",
    "    alpha = group.random(ZR)\n",
    "    g = group.random(G1)\n",
    "    return {'sk': alpha, 'pk': {'g': g, 'h': g ** alpha}}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "#### 2. build_index:\n",
    "对于关键词$w_i$, $B$首先选取随机数$r \\in Z_p^*$，并计算$t = e(H_1(w_i), h^r)$，随后输出该关键词对应的索引$C_i = (g^r, H_2(t)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def build_index(wi, pk):\n",
    "    r = group.random(ZR)\n",
    "    t = e(H1(wi), pk['h'] ** r)\n",
    "    return pk['g'] ** r, H2(obj2bytes(t))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "#### 3. generate_trapdoor\n",
    "对于查询关键词$w_i$，$A$使用私钥计算陷门$T_w = H_1(w)^\\alpha \\in G_1$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def generate_trapdoor(w, sk):\n",
    "    return H1(w) ** sk"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "#### 3. search\n",
    "对于索引$C_i = (A,B)$，如果$H_2(e(T_w, A)) = B$，则匹配成功，否则，匹配失败 \\\n",
    "正确性证明：\n",
    "$$\n",
    "\\begin{cases}\n",
    "\tH_2\\left( e\\left( T_w,A \\right) \\right) =H_2\\left( e\\left( H_1\\left( w \\right) ^{\\alpha},g^r \\right) \\right)\\\\\n",
    "\tB=H_2\\left( e\\left( H_1\\left( w \\right) ,h^r \\right) \\right) =H_2\\left( e\\left( H_1\\left( w \\right) ,g^{\\alpha r} \\right) \\right)\\\\\n",
    "\\end{cases}\n",
    "$$\n",
    "根据$ e\\left( g^x,g^y \\right) =e\\left( g,g \\right) ^{xy} $，易知上述两个公式相等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "def search(Ci, Tw):\n",
    "    A, B = Ci\n",
    "    return H2(obj2bytes(e(Tw, A))) == B"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 代码测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "key_pair:  {'sk': 428370243007372397337630840389621884192861434741, 'pk': {'g': [1497193766204690026589010503517406640570347028132384225137409724996440669604986657420706116398504109710601576543969824060663100384658513828307859616568814, 6595806344176136995619338736949793701449257775729385501675282746179537896777671207687125944222530956549128111634622693690443672415560189422343700040689823], 'h': [2581388103225427615587333514225260206017902274688598168865845995596191339150950875631352951262813639309846985388504871715767591936284497455033352494300377, 7675380495565676665671559577453423053248029976296047679061888744268762754925978111779460669884783659559264146444935923013016730369829066810505188267546704]}}\n",
      "Search happiness, Result: Yes\n"
     ]
    }
   ],
   "source": [
    "word_list = read_word_as_bytes('../test_files/happiness.txt')\n",
    "keyword = b'happiness'\n",
    "key_pair = setup()\n",
    "print('key_pair: ', key_pair)\n",
    "C = [build_index(w_i, key_pair['pk']) for w_i in word_list]\n",
    "T_w = generate_trapdoor(keyword, key_pair['sk'])\n",
    "print(f'Search {keyword.decode()}, Result: ', end = '')\n",
    "for C_i in C:\n",
    "    if search(C_i, T_w):\n",
    "        print('Yes')\n",
    "        break\n",
    "else:\n",
    "    print('No')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.7.9 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.9"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "d7eccc50bd8023cf74f021c24ed3740245f8543f295cddc81d7590622531cffd"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
